package com.ruoyi.net.service.impl;

import com.ruoyi.common.constant.ElementConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.GraphUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.GlobalCounter;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.net.domain.*;
import com.ruoyi.net.mapper.*;
import com.ruoyi.net.service.IBusiSrtpService;
import com.ruoyi.net.service.INetGroupService;
import com.ruoyi.net.utils.autoIncrement.GlobalIncrementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

import static com.ruoyi.net.service.impl.BusiMplstpServiceImpl.findTwoShortestArrays;

/**
 * 业务-srtp配置Service业务层处理
 *
 * @author net
 * @date 2024-12-05
 */
@Service
public class BusiSrtpServiceImpl implements IBusiSrtpService {
    @Autowired
    INetGroupService netGroupService;
    @Autowired
    BusiSrtpRouteGraphMapper busiSrtpRouteGraphMapper;
    @Autowired
    BusiSrtpRouteElementsMapper busiSrtpRouteElementsMapper;
    @Autowired
    BusiSrtpRouteTableMapper busiSrtpRouteTableMapper;
    @Autowired
    ElementPortModeMapper elementPortModeMapper;
    @Autowired
    GlobalIncrementService globalIncrementService;
    @Autowired
    private BusiSrtpMapper busiSrtpMapper;
    @Autowired
    private BusiSrtpConstraintMapper busiSrtpConstraintMapper;
    @Autowired
    private BusiSrtpRouteMapper busiSrtpRouteMapper;
    @Autowired
    private ElementBusiSrtpOtherMapper elementBusiSrtpOtherMapper;
    @Autowired
    private ElementBusiSrtpProtectMapper elementBusiSrtpProtectMapper;
    @Autowired
    private ElementBusiSrtpReroutingMapper elementBusiSrtpReroutingMapper;
    @Autowired
    private ElementBusiSrtpQosflowMapper elementBusiSrtpQosflowMapper;
    @Autowired
    private ElementBusiSrtpQoslspMapper elementBusiSrtpQoslspMapper;
    @Autowired
    private ElementBusiSrtpQoslevelMapper elementBusiSrtpQoslevelMapper;
    @Autowired
    private ElementBusiSrtpAlarmoamMapper elementBusiSrtpAlarmoamMapper;
    @Autowired
    private BusiSrtpElementMapper busiSrtpElementMapper;

    @Autowired
    BusiElementStatusMapper busiElementStatusMapper;

    @Autowired
    private BusiNeighbLabelMapper busiNeighbLabelMapper;

    private boolean hasFilterFlag = false;

    /**
     * 查询业务-srtp配置
     *
     * @param id 业务-srtp配置主键
     * @return 业务-srtp配置
     */
    @Override
    public BusiSrtp selectBusiSrtpById(String id) {
        return busiSrtpMapper.selectBusiSrtpById(id);
    }

    /**
     * 查询业务-srtp配置列表
     *
     * @param busiSrtp 业务-srtp配置
     * @return 业务-srtp配置
     */
    @Override
    public List<BusiSrtpListVo> selectBusiSrtpList(BusiSrtp busiSrtp) {
        return busiSrtpMapper.selectBusiSrtpList(busiSrtp);
    }

    /**
     * 新增业务-srtp配置
     *
     * @param busiSrtpVo 业务-srtp配置
     * @return 结果
     */
    @Override
    public int insertBusiSrtp(BusiSrtpVo busiSrtpVo) {
        String uuid = IdUtils.simpleUUID();
        if (StringUtils.isEmpty(busiSrtpVo.getId())) {
            busiSrtpVo.setId(uuid);
        }
        //  判断表中是否已存在该数据，存在则更新，否则新增
        if (busiSrtpMapper.selectBusiSrtpById(busiSrtpVo.getId()) != null) {
            //更新主表
            int i = busiSrtpMapper.updateBusiSrtp(busiSrtpVo);
            initUpdateBusiSrtpAttachInfo(busiSrtpVo);
            updateBusiSrtpRouteGraph(busiSrtpVo);
            //删除两张附表，重新绑定新数据
            busiSrtpRouteMapper.deleteBusiSrtpRouteBySrtpId(busiSrtpVo.getId());
            if (!CollectionUtils.isEmpty(busiSrtpVo.getBusiSrtpRouteList())) {
                for (BusiSrtpRoute busiSrtpRoute : busiSrtpVo.getBusiSrtpRouteList()) {
                    busiSrtpRoute.setId(IdUtils.simpleUUID());
                    busiSrtpRoute.setSrtpId(busiSrtpVo.getId());
                    busiSrtpRoute.setCreateBy(SecurityUtils.getUsername());
                    busiSrtpRoute.setCreateTime(DateUtils.getNowDate());
                    busiSrtpRoute.setUpdateBy(SecurityUtils.getUsername());
                    busiSrtpRoute.setUpdateTime(DateUtils.getNowDate());
                }
                busiSrtpRouteMapper.batchInsertBusiSrtpRoute(busiSrtpVo.getBusiSrtpRouteList());
            }
            return i;
        } else {
            //初始化新增SR-TP业务主表的各附属信息
            initInsertBusiSrtpAttachInfo(busiSrtpVo);
            //生成路由图数据
            insertBusiSrtpRouteGraph(busiSrtpVo);
            if (!CollectionUtils.isEmpty(busiSrtpVo.getBusiSrtpRouteList())) {
                for (BusiSrtpRoute busiSrtpRoute : busiSrtpVo.getBusiSrtpRouteList()) {
                    busiSrtpRoute.setId(IdUtils.simpleUUID());
                    busiSrtpRoute.setCreateBy(SecurityUtils.getUsername());
                    busiSrtpRoute.setCreateTime(DateUtils.getNowDate());
                    busiSrtpRoute.setUpdateBy(SecurityUtils.getUsername());
                    busiSrtpRoute.setUpdateTime(DateUtils.getNowDate());
                }
                //批量新增路由配置
                busiSrtpRouteMapper.batchInsertBusiSrtpRoute(busiSrtpVo.getBusiSrtpRouteList());
            }

            busiSrtpVo.setCreateBy(SecurityUtils.getUsername());
            busiSrtpVo.setCreateTime(DateUtils.getNowDate());
            busiSrtpVo.setUpdateBy(SecurityUtils.getUsername());
            busiSrtpVo.setUpdateTime(DateUtils.getNowDate());
            busiSrtpVo.setStatus(ElementConstants.STATUS_OFF);
            busiSrtpVo.setTunnelId(globalIncrementService.getNextTunnelIncrementNumber());
            return busiSrtpMapper.insertBusiSrtp(busiSrtpVo);
        }
    }

    /**
     * 初始化业务SR-TP附属信息
     *
     * @param busiSrtpVo
     */
    @Transactional(rollbackFor = Exception.class)
    void initInsertBusiSrtpAttachInfo(BusiSrtpVo busiSrtpVo) {
        //无保护默认生成一条数据
        if ("无保护".equals(busiSrtpVo.getProtectType())) {
            //调用qos-flow模版数据并新增
            insertBusiSrtpQosflowCommon(busiSrtpVo, "1");
            //调用qos-level模版数据并新增
            insertBusiSrtpQoslevelCommon(busiSrtpVo, "1");
            //调用qos-lsp模版数据并新增
            insertBusiSrtpQoslspCommon(busiSrtpVo, "1");

            if ("OAM".equals(busiSrtpVo.getFaultType())) {
                //工作路径-源网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "1", busiSrtpVo.getStartElement(), "start");
                //工作路径-宿网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "1", busiSrtpVo.getEndElement(), "end");
            }

        } else if ("1:1保护".equals(busiSrtpVo.getProtectType()) || "1:1保护带恢复".equals(busiSrtpVo.getProtectType())) {
            //故障检测类型新增四条数据
            if ("OAM".equals(busiSrtpVo.getFaultType())) {
                //工作路径-源网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "1", busiSrtpVo.getStartElement(), "start");
                //工作路径-宿网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "1", busiSrtpVo.getEndElement(), "end");
                //保护路径-源网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "2", busiSrtpVo.getStartElement(), "start");
                //保护路径-宿网元
                insertBusiSrtpAlarmoamCommon(busiSrtpVo, "2", busiSrtpVo.getEndElement(), "end");

            }
            //新增2条数据
            //调用qos-flow模版数据并新增
            insertBusiSrtpQosflowCommon(busiSrtpVo, "1");
            insertBusiSrtpQosflowCommon(busiSrtpVo, "2");
            //调用qos-level模版数据并新增
            insertBusiSrtpQoslevelCommon(busiSrtpVo, "1");
            insertBusiSrtpQoslevelCommon(busiSrtpVo, "2");
            //调用qos-lsp模版数据并新增
            insertBusiSrtpQoslspCommon(busiSrtpVo, "1");
            insertBusiSrtpQoslspCommon(busiSrtpVo, "2");
            //调用保护属性模版数据并新增
            ElementBusiSrtpProtect elementBusiSrtpProtect = elementBusiSrtpProtectMapper.selectElementBusiSrtpProtectTemplate();
            elementBusiSrtpProtect.setId(IdUtils.simpleUUID());
            elementBusiSrtpProtect.setSrtpId(busiSrtpVo.getId());
            elementBusiSrtpProtect.setUpdateBy(SecurityUtils.getUsername());
            elementBusiSrtpProtect.setUpdateTime(DateUtils.getNowDate());
            elementBusiSrtpProtect.setCreateBy(SecurityUtils.getUsername());
            elementBusiSrtpProtect.setCreateTime(DateUtils.getNowDate());
            elementBusiSrtpProtect.setTemplateFlag("N");
            elementBusiSrtpProtectMapper.insertElementBusiSrtpProtect(elementBusiSrtpProtect);
            if ("1:1保护带恢复".equals(busiSrtpVo.getProtectType())) {
                //调用重路由属性模版数据并新增
                ElementBusiSrtpRerouting elementBusiSrtpRerouting = elementBusiSrtpReroutingMapper.selectElementBusiSrtpProtectTemplate();
                elementBusiSrtpRerouting.setId(IdUtils.simpleUUID());
                elementBusiSrtpRerouting.setSrtpId(busiSrtpVo.getId());
                elementBusiSrtpRerouting.setUpdateBy(SecurityUtils.getUsername());
                elementBusiSrtpRerouting.setUpdateTime(DateUtils.getNowDate());
                elementBusiSrtpRerouting.setCreateBy(SecurityUtils.getUsername());
                elementBusiSrtpRerouting.setCreateTime(DateUtils.getNowDate());
                elementBusiSrtpRerouting.setTemplateFlag("N");
                elementBusiSrtpReroutingMapper.insertElementBusiSrtpRerouting(elementBusiSrtpRerouting);
            }

        }
        //调用其他属性模版数据并新增
        ElementBusiSrtpOther elementBusiSrtpOther = elementBusiSrtpOtherMapper.selectElementBusiSrtpOtherTemplate();
        elementBusiSrtpOther.setId(IdUtils.simpleUUID());
        elementBusiSrtpOther.setSrtpId(busiSrtpVo.getId());
        elementBusiSrtpOther.setUpdateBy(SecurityUtils.getUsername());
        elementBusiSrtpOther.setUpdateTime(DateUtils.getNowDate());
        elementBusiSrtpOther.setCreateBy(SecurityUtils.getUsername());
        elementBusiSrtpOther.setCreateTime(DateUtils.getNowDate());
        elementBusiSrtpOther.setTemplateFlag("N");
        elementBusiSrtpOtherMapper.insertElementBusiSrtpOther(elementBusiSrtpOther);
    }

    /**
     * 插入srtp-oam公共信息
     *
     * @param busiSrtpVo
     * @param routeType
     * @param elementId
     */
    private void insertBusiSrtpAlarmoamCommon(BusiSrtpVo busiSrtpVo, String routeType, String elementId, String nodeType) {
        ElementBusiSrtpAlarmoam elementBusiSrtpAlarmoam = elementBusiSrtpAlarmoamMapper.selectElementBusiSrtpAlarmoamTemplate();
        elementBusiSrtpAlarmoam.setId(IdUtils.simpleUUID());
        elementBusiSrtpAlarmoam.setRouteType(routeType);
        elementBusiSrtpAlarmoam.setElementId(elementId);
        elementBusiSrtpAlarmoam.setSrtpId(busiSrtpVo.getId());
        elementBusiSrtpAlarmoam.setUpdateBy(SecurityUtils.getUsername());
        elementBusiSrtpAlarmoam.setUpdateTime(DateUtils.getNowDate());
        elementBusiSrtpAlarmoam.setCreateBy(SecurityUtils.getUsername());
        elementBusiSrtpAlarmoam.setCreateTime(DateUtils.getNowDate());
        elementBusiSrtpAlarmoam.setTemplateFlag("N");
        //2.20修改
        elementBusiSrtpAlarmoam.setMegName("meg" + GlobalCounter.get10RandomToHexString());
        elementBusiSrtpAlarmoam.setMeName(globalIncrementService.getNextMeNameIncrementNumber());
        elementBusiSrtpAlarmoam.setOamId(globalIncrementService.getNextOamIdIncrementNumber());
        elementBusiSrtpAlarmoam.setNodeType(nodeType);
        elementBusiSrtpAlarmoamMapper.insertElementBusiSrtpAlarmoam(elementBusiSrtpAlarmoam);
    }

    /**
     * 插入SrtpQoslsp 公共信息
     *
     * @param busiSrtpVo
     * @param routeType
     */
    private void insertBusiSrtpQoslspCommon(BusiSrtpVo busiSrtpVo, String routeType) {
        //调用qos-lsp模版数据并新增
        ElementBusiSrtpQoslsp elementBusiSrtpQoslsp = elementBusiSrtpQoslspMapper.selectElementBusiSrtpQoslspTemplate();
        elementBusiSrtpQoslsp.setId(IdUtils.simpleUUID());
        elementBusiSrtpQoslsp.setSrtpId(busiSrtpVo.getId());
        elementBusiSrtpQoslsp.setRouteType(routeType);
        elementBusiSrtpQoslsp.setUpdateBy(SecurityUtils.getUsername());
        elementBusiSrtpQoslsp.setUpdateTime(DateUtils.getNowDate());
        elementBusiSrtpQoslsp.setCreateBy(SecurityUtils.getUsername());
        elementBusiSrtpQoslsp.setCreateTime(DateUtils.getNowDate());
        elementBusiSrtpQoslsp.setTemplateFlag("N");
        elementBusiSrtpQoslspMapper.insertElementBusiSrtpQoslsp(elementBusiSrtpQoslsp);
    }

    /**
     * 插入SrtpQoslevel 公共信息
     *
     * @param busiSrtpVo
     * @param routeType
     */
    private void insertBusiSrtpQoslevelCommon(BusiSrtpVo busiSrtpVo, String routeType) {
        ElementBusiSrtpQoslevel elementBusiSrtpQoslevel = elementBusiSrtpQoslevelMapper.selectElementBusiSrtpQoslevelTemplate();
        elementBusiSrtpQoslevel.setId(IdUtils.simpleUUID());
        elementBusiSrtpQoslevel.setSrtpId(busiSrtpVo.getId());
        elementBusiSrtpQoslevel.setRouteType(routeType);
        elementBusiSrtpQoslevel.setUpdateBy(SecurityUtils.getUsername());
        elementBusiSrtpQoslevel.setUpdateTime(DateUtils.getNowDate());
        elementBusiSrtpQoslevel.setCreateBy(SecurityUtils.getUsername());
        elementBusiSrtpQoslevel.setCreateTime(DateUtils.getNowDate());
        elementBusiSrtpQoslevel.setTemplateFlag("N");
        elementBusiSrtpQoslevelMapper.insertElementBusiSrtpQoslevel(elementBusiSrtpQoslevel);
    }

    /**
     * 插入SrtpQosflow 公共信息
     *
     * @param busiSrtpVo
     * @param routeType
     */
    private void insertBusiSrtpQosflowCommon(BusiSrtpVo busiSrtpVo, String routeType) {
        ElementBusiSrtpQosflow templateElementBusiSrtpQosflow = elementBusiSrtpQosflowMapper.selectElementBusiSrtpQosflowTemplate();
        templateElementBusiSrtpQosflow.setId(IdUtils.simpleUUID());
        templateElementBusiSrtpQosflow.setSrtpId(busiSrtpVo.getId());
        templateElementBusiSrtpQosflow.setRouteType(routeType);
        templateElementBusiSrtpQosflow.setUpdateBy(SecurityUtils.getUsername());
        templateElementBusiSrtpQosflow.setUpdateTime(DateUtils.getNowDate());
        templateElementBusiSrtpQosflow.setCreateBy(SecurityUtils.getUsername());
        templateElementBusiSrtpQosflow.setCreateTime(DateUtils.getNowDate());
        templateElementBusiSrtpQosflow.setTemplateFlag("N");
        elementBusiSrtpQosflowMapper.insertElementBusiSrtpQosflow(templateElementBusiSrtpQosflow);
    }

    /**
     * 初始化更新业务SR-TP附属信息
     *
     * @param busiSrtpVo
     */
    @Transactional(rollbackFor = Exception.class)
    void initUpdateBusiSrtpAttachInfo(BusiSrtpVo busiSrtpVo) {
        //先删除附属表信息，再重新插入
        elementBusiSrtpQosflowMapper.deleteElementBusiSrtpQosflowBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpQoslevelMapper.deleteElementBusiSrtpQoslevelBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpQoslspMapper.deleteElementBusiSrtpQoslspBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpAlarmoamMapper.deleteElementBusiSrtpAlarmoamBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpOtherMapper.deleteElementBusiSrtpOtherBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpProtectMapper.deleteElementBusiSrtpProtectBySrtpId(busiSrtpVo.getId());
        elementBusiSrtpReroutingMapper.deleteElementBusiSrtpReroutingBySrtpId(busiSrtpVo.getId());
        //删除单站业务表
        busiSrtpElementMapper.deleteBusiSrtpElementBySrtpId(busiSrtpVo.getId());
        busiElementStatusMapper.deleteBusiElementStatusBySrtpId(busiSrtpVo.getId());
        initInsertBusiSrtpAttachInfo(busiSrtpVo);

    }

    /**
     * Srtp生成路由图表
     *
     * @param
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertBusiSrtpRouteGraph(BusiSrtpVo busiSrtpVo) {
        NetGroup netGroup = netGroupService.selectNetGroupById(busiSrtpVo.getStartElement());
        //源宿节点的父id:
        String parentId = netGroup.getParentId();
        Map<String, Integer> indexMap = new HashMap<String, Integer>();
        Set<String> idsUnique = new HashSet<>();
        List<TopoVo> topoVos1 = netGroupService.selectTopo(parentId);
        List<TopoVo> topoVos = new ArrayList<>();

        //获取总节点数组 并过滤eth  PortMode 为enable 2.11修改
        //3.16修改获取总节点数组 并过滤eth、虚拟(小颗粒)  PortMode 为enable或者veth
        for (TopoVo topoVo : topoVos1) {
            if (!CollectionUtils.isEmpty(topoVo.getLinkData())) {
                String startPortId = topoVo.getLinkData().get(0).getStartPortId();
                String endPortId = topoVo.getLinkData().get(0).getEndPortId();
                ElementPortMode startElementPortMode = elementPortModeMapper.selectElementPortModeById(startPortId);
                ElementPortMode endElementPortMode = elementPortModeMapper.selectElementPortModeById(endPortId);
                if (!"disable".equals(startElementPortMode.getPortMode()) && !"disable".equals(endElementPortMode.getPortMode())) {
                    topoVos.add(topoVo);
                }
            }
        }
        for (TopoVo topoVo : topoVos) {
            idsUnique.add(topoVo.getToId());
            idsUnique.add(topoVo.getFromId());
        }
        List<String> ids = new ArrayList<>(idsUnique);
        for (int i = 0; i < ids.size(); i++) {
            indexMap.put(ids.get(i), i);
        }
        Map<String, String> elementMap = new HashMap<String, String>();
        //构造双向线段
        for (TopoVo topoVo : topoVos) {
            elementMap.put(topoVo.getFromId(), topoVo.getFromName());
            elementMap.put(topoVo.getToId(), topoVo.getToName());

        }
        //获取总节点个数
        GraphUtil.Graph graph = new GraphUtil.Graph(ids.size());
        //构建路由对象
        for (int i = 0; i < topoVos.size(); i++) {
            graph.addEdge(indexMap.get(topoVos.get(i).getFromId()), indexMap.get(topoVos.get(i).getToId()));
            graph.addEdge(indexMap.get(topoVos.get(i).getToId()), indexMap.get(topoVos.get(i).getFromId()));

        }
        List<List<Integer>> paths = graph.allPathsSourceToDestination(indexMap.get(busiSrtpVo.getStartElement()), indexMap.get(busiSrtpVo.getEndElement()));
        List<List<String>> listIds = new ArrayList<>();
        Set<List<String>> listIdsUnq = new HashSet<>();

        for (List<Integer> path : paths) {
            List<String> list = new ArrayList<>();
            for (Integer integer : path) {
                list.add(ids.get(integer));
            }
            listIdsUnq.add(list);
            listIds.add(list);
        }
        //去重的线路set转list
        List<List<String>> filterList = new ArrayList<>(listIdsUnq);
        List<List<String>> filterList2 = new ArrayList<>();

        //是否有过滤约束
        hasFilterConstrant(busiSrtpVo);
        //todo 将所有的路由列举，添加过滤策略，过滤后的结果（工作、保护）入库
        List<List<NetElementLinkVo>> resultByFilter = filterRouteLineByConstraint(listIdsUnq, topoVos, busiSrtpVo);
        //获取两条最短路径，含vo对象
        List<List<NetElementLinkVo>> twoShortestInfos = findTwoShortestArrays(resultByFilter);
        for (List<NetElementLinkVo> netElementLinkVos : twoShortestInfos) {
            List<String> filters = new ArrayList<>();
            for (NetElementLinkVo netElementLinkVo : netElementLinkVos) {
                filters.add(netElementLinkVo.getStartElementId());
                filters.add(netElementLinkVo.getEndElementId());
            }
            List<String> toList = new ArrayList<>(filters);
            LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>(filters);
            List<String> arrayList = new ArrayList<>(linkedHashSet);
            filterList2.add(arrayList);
        }
        //声明两条最短路径 只含网元
        List<List<String>> finalRouteResultNoFilter = new ArrayList<>();
        if (hasFilterFlag) {
            finalRouteResultNoFilter = GraphUtil.findTwoShortestArrays(filterList2);
        } else {
            finalRouteResultNoFilter = GraphUtil.findTwoShortestArrays(listIds);
        }

        /**
         * 1、如果是无保护存工作路径  直接取第一个最小数组,如果是1:1则取整个数组（两条最短路径），
         * 生成保护存工作路径、保护路径，然后构造fromId toId linkData
         * 2、将最短路径分隔成有向的n条线段
         * 3、将所有线段与topo图对比，获取属性全部信息
         * 4、将结果属性全部信息存入数据库
         */
        if ("无保护".equals(busiSrtpVo.getProtectType())) {
            if (finalRouteResultNoFilter.size() < 1 ||twoShortestInfos.size() < 1) {
                throw new ServiceException("计算条件不足");
            }
            List<String> shortestRoute = finalRouteResultNoFilter.get(0);
            //插入一条保护路径网元信息（附带顺序）
            insertBusiSrtpRouteElementsBatch(busiSrtpVo.getId(), shortestRoute, elementMap, "1");
            List<List<String>> allLines = GraphUtil.cutRouteToLine(shortestRoute);
            System.out.println("所有线段: " + allLines);
            //生成路由图
            if (hasFilterFlag) {
                insertBusiSrtpRouteGraphCommon2(busiSrtpVo, twoShortestInfos.get(0), "1");
            } else {
                insertBusiSrtpRouteGraphCommon(busiSrtpVo, topoVos, allLines, "1");
            }

            insertBusiSrtpRouteTableCommon(busiSrtpVo, allLines, twoShortestInfos.get(0), "1", "1", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, allLines, twoShortestInfos.get(0), "1", "1", "N");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, allLines, twoShortestInfos.get(0), "1", "2", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, allLines, twoShortestInfos.get(0), "1", "2", "N");
            //4.11  新增srtp单站业务表-工作（逻辑：工作路径每个网元生成一条待激活单站业务数据）
            insertBusiSrtpElement("1", busiSrtpVo, shortestRoute);
            //找到当前业务下所有网元，并入库至业务设备状态表并设置初始状态
            initBusiMplsElementStatus(busiSrtpVo.getId(), finalRouteResultNoFilter);
        } else if ("1:1保护".equals(busiSrtpVo.getProtectType()) || "1:1保护带恢复".equals(busiSrtpVo.getProtectType())) {
            if (finalRouteResultNoFilter.size() < 2 ||twoShortestInfos.size() < 2) {
                throw new ServiceException("计算条件不足");
            }
            //如果是1:1保护 则取整个数组（两条最短路径），生成保护存工作路径、保护路径，然后构造fromId toId linkData
            //线路1所有线段
            List<String> shortestRoute1 = finalRouteResultNoFilter.get(0);
            //插入一条保护路径网元信息（附带顺序）
            insertBusiSrtpRouteElementsBatch(busiSrtpVo.getId(), shortestRoute1, elementMap, "1");
            List<List<String>> workAllLines1 = GraphUtil.cutRouteToLine(shortestRoute1);

            //生成路由图
            if (hasFilterFlag) {
                insertBusiSrtpRouteGraphCommon2(busiSrtpVo, twoShortestInfos.get(0), "1");
            } else {
                insertBusiSrtpRouteGraphCommon(busiSrtpVo, topoVos, workAllLines1, "1");
            }
            insertBusiSrtpElement("1", busiSrtpVo, finalRouteResultNoFilter.get(0));
            //线路2所有线段
            //插入一条保护路径网元信息（附带顺序）
            insertBusiSrtpRouteElementsBatch(busiSrtpVo.getId(), finalRouteResultNoFilter.get(1), elementMap, "2");
            List<List<String>> workAllLines2 = GraphUtil.cutRouteToLine(finalRouteResultNoFilter.get(1));

            //生成路由图
            if (hasFilterFlag) {
                insertBusiSrtpRouteGraphCommon2(busiSrtpVo, twoShortestInfos.get(1), "2");
            } else {
                insertBusiSrtpRouteGraphCommon(busiSrtpVo, topoVos, workAllLines2, "2");
            }
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines1, twoShortestInfos.get(0), "1", "1", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines1, twoShortestInfos.get(0), "1", "1", "N");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines1, twoShortestInfos.get(0), "1", "2", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines1, twoShortestInfos.get(0), "1", "2", "N");

            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines2, twoShortestInfos.get(1), "2", "1", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines2, twoShortestInfos.get(1), "2", "1", "N");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines2, twoShortestInfos.get(1), "2", "2", "Y");
            insertBusiSrtpRouteTableCommon(busiSrtpVo, workAllLines2, twoShortestInfos.get(1), "2", "2", "N");
            insertBusiSrtpElement("1", busiSrtpVo, finalRouteResultNoFilter.get(1));
            //找到当前业务下所有网元，并入库至业务设备状态表并设置初始状态
            initBusiMplsElementStatus(busiSrtpVo.getId(), finalRouteResultNoFilter);
        }
        System.out.println("最终结果: " + finalRouteResultNoFilter);
    }
    /**
     * 找到当前业务下所有不重复网元，
     * 并入库至业务设备状态表并设置初始状态
     *
     * @param srtpId         主业务id
     * @param finalRouteResult 最短两条线集合
     */
    private void initBusiMplsElementStatus(String srtpId, List<List<String>> finalRouteResult) {
        HashSet<String> uniqueElement = new HashSet<>();
        //找出不重复的网元
        for (List<String> oneRoute : finalRouteResult) {
            for (String elementId : oneRoute) {
                uniqueElement.add(elementId);
            }
        }
        //入库至业务设备状态表并设置初始状态
        for (String elementId : uniqueElement) {
            BusiElementStatus busiElementStatus = new BusiElementStatus();
            busiElementStatus.setElementId(elementId);
            busiElementStatus.setBusiId(srtpId);
            busiElementStatus.setId(IdUtils.simpleUUID());
            busiElementStatus.setStatus("0");
            busiElementStatus.setBusiType(ElementConstants.BUSI_SRTP);
            busiElementStatus.setCreateBy(SecurityUtils.getUsername());
            busiElementStatus.setCreateTime(DateUtils.getNowDate());
            busiElementStatusMapper.insertBusiElementStatus(busiElementStatus);
        }
    }

    /**
     * srtp单站业务表插入数据
     * @param routeType
     * @param busiSrtpVo
     * @param shortestRoute routeType 1:工作  2：保护
     */
    private void insertBusiSrtpElement(String routeType, BusiSrtpVo busiSrtpVo, List<String> shortestRoute) {

        //无保护  生成条数与网元数一致
        for (int i = 0; i < shortestRoute.size(); i++) {
            BusiSrtpElement busiSrtpElement = new BusiSrtpElement();
            busiSrtpElement.setId(IdUtils.simpleUUID());
            busiSrtpElement.setSrtpId(busiSrtpVo.getId());
            busiSrtpElement.setElementId(shortestRoute.get(i));
            busiSrtpElement.setCreateBy(SecurityUtils.getUsername());
            busiSrtpElement.setCreateTime(DateUtils.getNowDate());
            busiSrtpElement.setUpdateBy(SecurityUtils.getUsername());
            busiSrtpElement.setUpdateTime(DateUtils.getNowDate());
            busiSrtpElement.setRouteType(routeType);
            if (i == 0) {
                //1=：源,2=：宿,3=：,过=站
                busiSrtpElement.setElementType("1");
            } else if (i == shortestRoute.size() - 1) {
                busiSrtpElement.setElementType("2");
            } else {
                busiSrtpElement.setElementType("3");
            }
            busiSrtpElement.setPositiveTunnelId(globalIncrementService.getNextTunnelIncrementNumber());//???用的太多   不唯一性
            busiSrtpElement.setCircuitDirection("双向");
            busiSrtpElementMapper.insertBusiSrtpElement(busiSrtpElement);
        }
    }

    private List<List<NetElementLinkVo>> filterRouteLineByConstraint(Set<List<String>> allLines2, List<TopoVo> topoVos, BusiSrtpVo busiSrtpVo) {
        List<List<String>> allLines = new ArrayList<>(allLines2);
        List<TopoVo> topoVoSort = new ArrayList<>();
        List<MidVo> midLines = new ArrayList<>();
        //将计算的路由线路转换为topo
        for (int i = 0; i < allLines.size(); i++) {
            List<List<NetElementLinkVo>> subLines = new ArrayList<>();
            MidVo midVo = new MidVo();
            List<List<String>> lines = GraphUtil.cutRouteToLine(allLines.get(i));
            midVo.setElements(allLines.get(i));
            for (int j = 0; j < lines.size(); j++) {
                List<NetElementLinkVo> netElementLinkVos = new ArrayList<>();
                for (int k = 0; k < topoVos.size(); k++) {
                    if ((lines.get(j).get(0).equals(topoVos.get(k).getFromId()) && lines.get(j).get(1).equals(topoVos.get(k).getToId())) || (lines.get(j).get(1).equals(topoVos.get(k).getFromId()) && lines.get(j).get(0).equals(topoVos.get(k).getToId()))) {
                        topoVoSort.add(topoVos.get(k));
                        netElementLinkVos.add(topoVos.get(k).getLinkData().get(0));
                    }
                }
                subLines.add(netElementLinkVos);
            }
            midVo.setSubLines(subLines);
            midLines.add(midVo);
        }
        //所有路由结果
        List<List<NetElementLinkVo>> combinLineInfo = new ArrayList<>();
        for (int i = 0; i < midLines.size(); i++) {
            List<List<NetElementLinkVo>> combinations = combine(midLines.get(i).getSubLines());
            for (List<NetElementLinkVo> combinations1 : combinations) {
                for (NetElementLinkVo netElementLinkVo : combinations1) {
                    netElementLinkVo.setElements(midLines.get(i).getElements());
                }
            }
            combinLineInfo.addAll(combinations);
        }
        List<List<NetElementLinkVo>> finalResult = new ArrayList<>();
        //处理网元过滤
        BusiSrtpConstraint busiSrtpConstraint = new BusiSrtpConstraint();
        busiSrtpConstraint.setSrtpId(busiSrtpVo.getId());
        busiSrtpConstraint.setConstraintType("网元");
        List<BusiSrtpConstraint> busiSrtpConstraints = busiSrtpConstraintMapper.selectBusiSrtpConstraintList(busiSrtpConstraint);
        if (!CollectionUtils.isEmpty(busiSrtpConstraints)) {
            for (List<NetElementLinkVo> lineObjs : combinLineInfo) {
                for (BusiSrtpConstraint constraint : busiSrtpConstraints) {
                    List<NetElementLinkVo> oneRoute = new ArrayList<>();
                    //处理网元包含、不包含逻辑
                    if ("包含".equals(constraint.getConstraintStrategy())) {
                        for (NetElementLinkVo lineObj : lineObjs) {
                            if (lineObj.getStartElementId().equals(constraint.getElementId()) || lineObj.getEndElementId().equals(constraint.getElementId())) {
                                oneRoute.add(lineObj);
                            }
                        }
                    } else {
                        for (NetElementLinkVo lineObj : lineObjs) {
                            if (!lineObj.getStartElementId().equals(constraint.getElementId()) && !lineObj.getEndElementId().equals(constraint.getElementId())) {
                                oneRoute.add(lineObj);
                            }
                        }
                    }
                    if (oneRoute.size() > 0) {
                        finalResult.add(oneRoute);
                    }
                }
            }
        } else {
            finalResult = combinLineInfo;
        }

        List<List<NetElementLinkVo>> finalResult2 = new ArrayList<>();
        //处理端口过滤
        busiSrtpConstraint.setConstraintType("端口");
        List<BusiSrtpConstraint> busiSrtpConstraints2 = busiSrtpConstraintMapper.selectBusiSrtpConstraintList(busiSrtpConstraint);
        if (!CollectionUtils.isEmpty(busiSrtpConstraints2)) {
            for (List<NetElementLinkVo> lineObjs : finalResult) {
                List<NetElementLinkVo> oneRoute = new ArrayList<>();
                for (BusiSrtpConstraint constraint : busiSrtpConstraints2) {
                    //处理网元包含、不包含逻辑
                    if ("包含".equals(constraint.getConstraintStrategy())) {
                        for (NetElementLinkVo lineObj : lineObjs) {
                            if (lineObj.getStartPortId().equals(constraint.getPortId()) || lineObj.getEndPortId().equals(constraint.getPortId())) {
                                oneRoute.add(lineObj);
                            }
                        }
                    } else {
                        for (NetElementLinkVo lineObj : lineObjs) {
                            if (!lineObj.getStartPortId().equals(constraint.getPortId()) && !lineObj.getEndPortId().equals(constraint.getPortId())) {
                                oneRoute.add(lineObj);
                            }
                        }
                    }
                    if (oneRoute.size() > 0) {
                        finalResult2.add(oneRoute);
                    }
                }
            }
        } else {
            finalResult2 = finalResult;
        }

        return finalResult2;
    }

    private boolean hasFilterConstrant(BusiSrtpVo busiSrtpVo) {
        BusiSrtpConstraint busiSrtpConstraint = new BusiSrtpConstraint();
        busiSrtpConstraint.setSrtpId(busiSrtpVo.getId());
        List<BusiSrtpConstraint> busiSrtpConstraints = busiSrtpConstraintMapper.selectBusiSrtpConstraintList(busiSrtpConstraint);
        hasFilterFlag = !CollectionUtils.isEmpty(busiSrtpConstraints);
        return hasFilterFlag;
    }

    private void insertBusiSrtpRouteGraphCommon(BusiSrtpVo busiSrtpVo, List<TopoVo> topoVos, List<List<String>> workAllLines1, String routeType) {
        //将所有线段与topo图对比，获取属性全部信息
        List<TopoVo> topoVoSort = new ArrayList<>();

        for (int i = 0; i < workAllLines1.size(); i++) {
            for (int j = 0; j < topoVos.size(); j++) {
                //用返回最短路径结果与topo图对比，获取属性全部信息
                if ((workAllLines1.get(i).get(0).equals(topoVos.get(j).getFromId()) && workAllLines1.get(i).get(1).equals(topoVos.get(j).getToId())) || (workAllLines1.get(i).get(1).equals(topoVos.get(j).getFromId()) && workAllLines1.get(i).get(0).equals(topoVos.get(j).getToId()))) {
                    topoVoSort.add(topoVos.get(j));
                }
            }
        }


        String pathId1 = IdUtils.simpleUUID();
        for (int j = 0; j < topoVoSort.size(); j++) {
            for (int i = 0; i < workAllLines1.size(); i++) {
                //用返回最短路径结果与topo图对比，获取属性全部信息
                if ((topoVoSort.get(j).getFromId().equals(workAllLines1.get(i).get(0)) && topoVoSort.get(j).getToId().equals(workAllLines1.get(i).get(1))) || (topoVoSort.get(j).getFromId().equals(workAllLines1.get(i).get(1)) && topoVoSort.get(j).getToId().equals(workAllLines1.get(i).get(0)))) {
                    //避免重复插入脏数据
                    BusiSrtpRouteGraph busiSrtpRouteGraphSearchParam = new BusiSrtpRouteGraph();
                    busiSrtpRouteGraphSearchParam.setSrtpId(busiSrtpVo.getId());
                    busiSrtpRouteGraphSearchParam.setFromId(topoVoSort.get(j).getFromId());
                    busiSrtpRouteGraphSearchParam.setToId(topoVoSort.get(j).getToId());
                    busiSrtpRouteGraphSearchParam.setPathId(pathId1);
                    List<BusiSrtpRouteGraph> busiSrtpRouteGraphList = busiSrtpRouteGraphMapper.selectBusiSrtpRouteGraphList(busiSrtpRouteGraphSearchParam);
                    if (CollectionUtils.isEmpty(busiSrtpRouteGraphList)) {
                        BusiSrtpRouteGraph testRouteEntity = new BusiSrtpRouteGraph();
                        if (StringUtils.isEmpty(testRouteEntity.getId())) {
                            testRouteEntity.setId(IdUtils.simpleUUID());
                        }
                        testRouteEntity.setRouteType(routeType);
                        //线路id  用于区分同一个SrtpId下 的多条线路
                        testRouteEntity.setPathId(pathId1);
                        //主表主键
                        testRouteEntity.setSrtpId(busiSrtpVo.getId());
                        testRouteEntity.setFromId(workAllLines1.get(i).get(0));
                        testRouteEntity.setToId(workAllLines1.get(i).get(1));
                        String fromNameFlag = "from";
                        if (topoVoSort.get(j).getFromId().equals(workAllLines1.get(i).get(0))) {

                        } else {
                            fromNameFlag = "to";
                        }
                        if ("from".equals(fromNameFlag)) {
                            testRouteEntity.setFromName(topoVoSort.get(j).getFromName());
                            testRouteEntity.setToName(topoVoSort.get(j).getToName());
                            testRouteEntity.setStartPortId(topoVoSort.get(j).getLinkData().get(0).getStartPortId());
                            testRouteEntity.setStartPort(topoVoSort.get(j).getLinkData().get(0).getStartPort());
                            testRouteEntity.setEndPortId(topoVoSort.get(j).getLinkData().get(0).getEndPortId());
                            testRouteEntity.setEndPort(topoVoSort.get(j).getLinkData().get(0).getEndPort());
                        } else {
                            testRouteEntity.setFromName(topoVoSort.get(j).getToName());
                            testRouteEntity.setToName(topoVoSort.get(j).getFromName());
                            testRouteEntity.setStartPortId(topoVoSort.get(j).getLinkData().get(0).getEndPortId());
                            testRouteEntity.setStartPort(topoVoSort.get(j).getLinkData().get(0).getEndPort());
                            testRouteEntity.setEndPortId(topoVoSort.get(j).getLinkData().get(0).getStartPortId());
                            testRouteEntity.setEndPort(topoVoSort.get(j).getLinkData().get(0).getStartPort());
                        }

                        testRouteEntity.setCreateBy(SecurityUtils.getUsername());
                        testRouteEntity.setCreateTime(DateUtils.getNowDate());
                        testRouteEntity.setUpdateBy(SecurityUtils.getUsername());
                        testRouteEntity.setUpdateTime(DateUtils.getNowDate());
                        busiSrtpRouteGraphMapper.insertBusiSrtpRouteGraph(testRouteEntity);
                        //插入一条与实际方向相反的数据，方便前端展示双向效果
                        testRouteEntity.setId(IdUtils.simpleUUID());
                        if ("from".equals(fromNameFlag)) {
                            testRouteEntity.setFromName(topoVoSort.get(j).getToName());
                            testRouteEntity.setToName(topoVoSort.get(j).getFromName());
                            testRouteEntity.setStartPortId(topoVoSort.get(j).getLinkData().get(0).getEndPortId());
                            testRouteEntity.setEndPortId(topoVoSort.get(j).getLinkData().get(0).getStartPortId());
                            testRouteEntity.setStartPort(topoVoSort.get(j).getLinkData().get(0).getEndPort());
                            testRouteEntity.setEndPort(topoVoSort.get(j).getLinkData().get(0).getStartPort());
                        } else {
                            testRouteEntity.setFromName(topoVoSort.get(j).getFromName());
                            testRouteEntity.setToName(topoVoSort.get(j).getToName());
                            testRouteEntity.setStartPortId(topoVoSort.get(j).getLinkData().get(0).getStartPortId());
                            testRouteEntity.setEndPortId(topoVoSort.get(j).getLinkData().get(0).getEndPortId());
                            testRouteEntity.setStartPort(topoVoSort.get(j).getLinkData().get(0).getStartPort());
                            testRouteEntity.setEndPort(topoVoSort.get(j).getLinkData().get(0).getEndPort());
                        }
                        testRouteEntity.setFromId(workAllLines1.get(i).get(1));
                        testRouteEntity.setToId(workAllLines1.get(i).get(0));

                        busiSrtpRouteGraphMapper.insertBusiSrtpRouteGraph(testRouteEntity);
                    }
                }
            }
        }
    }

    private void insertBusiSrtpRouteGraphCommon2(BusiSrtpVo busiSrtpVo, List<NetElementLinkVo> randomLinks, String routeType) {

        List<List<String>> allLines2 = new ArrayList<>();
        List<NetElementLinkVo> netElementLinkVos = new ArrayList<>();
        allLines2 = GraphUtil.cutRouteToLine(randomLinks.get(0).getElements());
        //将topo图按照线段排序
        for (int i = 0; i < allLines2.size(); i++) {
            for (int j = 0; j < randomLinks.size(); j++) {
                if ((allLines2.get(i).get(0).equals(randomLinks.get(j).getStartElementId()) && allLines2.get(i).get(1).equals(randomLinks.get(j).getEndElementId())) || (allLines2.get(i).get(1).equals(randomLinks.get(j).getStartElementId()) && allLines2.get(i).get(0).equals(randomLinks.get(j).getEndElementId()))) {
                    netElementLinkVos.add(randomLinks.get(j));
                }
            }
        }
        String pathId1 = IdUtils.simpleUUID();
        List<String> oneRoute = new ArrayList<>();

        for (int j = 0; j < netElementLinkVos.size(); j++) {
            oneRoute = netElementLinkVos.get(j).getElements();
            List<List<String>> allLines = GraphUtil.cutRouteToLine(oneRoute);
            //避免重复插入脏数据
            BusiSrtpRouteGraph busiSrtpRouteGraphSearchParam = new BusiSrtpRouteGraph();
            busiSrtpRouteGraphSearchParam.setSrtpId(busiSrtpVo.getId());
            busiSrtpRouteGraphSearchParam.setFromId(netElementLinkVos.get(j).getStartElementId());
            busiSrtpRouteGraphSearchParam.setToId(netElementLinkVos.get(j).getEndElementId());
            busiSrtpRouteGraphSearchParam.setPathId(pathId1);
            List<BusiSrtpRouteGraph> busiSrtpRouteGraphList = busiSrtpRouteGraphMapper.selectBusiSrtpRouteGraphList(busiSrtpRouteGraphSearchParam);
            if (CollectionUtils.isEmpty(busiSrtpRouteGraphList)) {
                BusiSrtpRouteGraph testRouteEntity = new BusiSrtpRouteGraph();
                if (StringUtils.isEmpty(testRouteEntity.getId())) {
                    testRouteEntity.setId(IdUtils.simpleUUID());
                }
                testRouteEntity.setRouteType(routeType);
                //线路id  用于区分同一个SrtpId下 的多条线路
                testRouteEntity.setPathId(pathId1);
                //主表主键
                testRouteEntity.setSrtpId(busiSrtpVo.getId());
                testRouteEntity.setFromId(allLines.get(j).get(0));
                testRouteEntity.setToId(allLines.get(j).get(1));
                String fromNameFlag = "from";
               /* if (topoVoSort.get(j).getFromId().equals(workAllLines1.get(i).get(0))){

                }else{
                    fromNameFlag ="to";
                }*/
                testRouteEntity.setFromName(netElementLinkVos.get(j).getStartName());
                testRouteEntity.setToName(netElementLinkVos.get(j).getEndName());
                testRouteEntity.setStartPortId(netElementLinkVos.get(j).getStartPortId());
                testRouteEntity.setStartPort(netElementLinkVos.get(j).getStartPort());
                testRouteEntity.setEndPortId(netElementLinkVos.get(j).getEndPortId());
                testRouteEntity.setEndPort(netElementLinkVos.get(j).getEndPort());

                testRouteEntity.setCreateBy(SecurityUtils.getUsername());
                testRouteEntity.setCreateTime(DateUtils.getNowDate());
                testRouteEntity.setUpdateBy(SecurityUtils.getUsername());
                testRouteEntity.setUpdateTime(DateUtils.getNowDate());
                busiSrtpRouteGraphMapper.insertBusiSrtpRouteGraph(testRouteEntity);
                //插入一条与实际方向相反的数据，方便前端展示双向效果
                testRouteEntity.setId(IdUtils.simpleUUID());
                testRouteEntity.setFromName(netElementLinkVos.get(j).getEndName());
                testRouteEntity.setToName(netElementLinkVos.get(j).getStartName());
                testRouteEntity.setStartPortId(netElementLinkVos.get(j).getEndPortId());
                testRouteEntity.setEndPortId(netElementLinkVos.get(j).getStartPortId());
                testRouteEntity.setStartPort(netElementLinkVos.get(j).getEndPort());
                testRouteEntity.setEndPort(netElementLinkVos.get(j).getStartPort());
                testRouteEntity.setFromId(allLines.get(j).get(1));
                testRouteEntity.setToId(allLines.get(j).get(0));
                testRouteEntity.setCreateTime(DateUtils.getNowDate());
                busiSrtpRouteGraphMapper.insertBusiSrtpRouteGraph(testRouteEntity);
            }
        }


    }

    /**
     * 插入Srtp路由表公共方法
     *
     * @param busiSrtpVo
     * @param allLines
     * @param routeType
     */
    private void insertBusiSrtpRouteTableCommon(BusiSrtpVo busiSrtpVo, List<List<String>> allLines, List<NetElementLinkVo> links, String routeType, String routeDirection, String flag) {
        //是否有路由约束
        if (hasFilterFlag) {
            //正向
            if ("1".equals(routeDirection)) {
                for (int i = 0; i < links.size(); i++) {
                    NetElementLinkVo link = links.get(i);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, link.getStartElementId(), link.getStartPortId(), link.getStartPort(), flag, 2 * i + 1);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, link.getEndElementId(), link.getEndPortId(), link.getEndPort(), flag, 2 * i + 2);
                }

            } else {
                //反向
                for (int i = links.size(); i > 0; i--) {
                    NetElementLinkVo link = links.get(i - 1);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, link.getEndElementId(), link.getEndPortId(), link.getEndPort(), flag, 2 * i + 2);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, link.getStartElementId(), link.getStartPortId(), link.getStartPort(), flag, 2 * i + 1);
                }
            }
        } else {
            BusiSrtpRouteGraph busiSrtpRouteGraph = new BusiSrtpRouteGraph();
            busiSrtpRouteGraph.setSrtpId(busiSrtpVo.getId());
            busiSrtpRouteGraph.setRouteType(routeType);
            //查询路由图 包含构造的逆向数据
            List<BusiSrtpRouteGraph> busiSrtpRouteGraphs = busiSrtpRouteGraphMapper.selectBusiSrtpRouteGraphList(busiSrtpRouteGraph);
            //过滤非构造线段属性
            List<BusiSrtpRouteGraph> filterResult = new ArrayList<>();
            //按照顺序分割好的线段与路由图对比取 link属性
            for (int i = 0; i < allLines.size(); i++) {
                for (int j = 0; j < busiSrtpRouteGraphs.size(); j++) {
                    if (allLines.get(i).get(0).equals(busiSrtpRouteGraphs.get(j).getFromId()) && allLines.get(i).get(1).equals(busiSrtpRouteGraphs.get(j).getToId())) {
                        filterResult.add(busiSrtpRouteGraphs.get(j));
                    }
                }
            }
            //正向
            if ("1".equals(routeDirection)) {
                for (int i = 0; i < filterResult.size(); i++) {
                    BusiSrtpRouteGraph graph = filterResult.get(i);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, graph.getFromId(), graph.getStartPortId(), graph.getStartPort(), flag, 2 * i + 1);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, graph.getToId(), graph.getEndPortId(), graph.getEndPort(), flag, 2 * i + 2);
                }
            } else {
                int j = 0;
                for (int i = filterResult.size(); i > 0; i--) {
                    BusiSrtpRouteGraph graph = filterResult.get(i - 1);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, graph.getToId(), graph.getEndPortId(), graph.getEndPort(), flag, 2 * j + 2);
                    insertBusiSrtpRouteTable(busiSrtpVo, routeDirection, routeType, graph.getFromId(), graph.getStartPortId(), graph.getStartPort(), flag, 2 * j + 1);
                    j++;
                }
            }
        }

    }

    /**
     * 插入路由表数据
     * @param busiSrtpVo
     * @param routeDirection
     * @param routeType
     * @param elementId
     * @param portId
     * @param portName
     * @param flag
     * @param seq
     */
    private void insertBusiSrtpRouteTable(BusiSrtpVo busiSrtpVo, String routeDirection, String routeType, String elementId, String portId, String portName, String flag, int seq) {
        BusiSrtpRouteTable busiSrtpRouteTable = new BusiSrtpRouteTable();
        busiSrtpRouteTable.setId(IdUtils.simpleUUID());
        busiSrtpRouteTable.setServiceFlag(flag);
        busiSrtpRouteTable.setSrtpId(busiSrtpVo.getId());
        busiSrtpRouteTable.setRouteDirection(routeDirection);
        busiSrtpRouteTable.setRouteType(routeType);
        busiSrtpRouteTable.setElementId(elementId);
        busiSrtpRouteTable.setPortId(portId);
        if (!"Y".equals(flag)) {
            busiSrtpRouteTable.setPortName("SR-1");
        }
        busiSrtpRouteTable.setTerminalLabel("");
        //4.15修改逻辑  邻接标签取值来源于与邻接标签表对比，条件为startElement 、startPortName
        //srtp下的邻接标签条件 L3 使能 ip同网段
        String neibLabel = findNeibLabelByParams(elementId, portId);
        if("".equals(neibLabel)){
            throw new ServiceException("无邻接标签，计算条件不足");
        }
        busiSrtpRouteTable.setNeighbLabel(neibLabel);
        busiSrtpRouteTable.setStickNodeFlag("N");
        busiSrtpRouteTable.setStickLabel("");
        busiSrtpRouteTable.setCreateBy(SecurityUtils.getUsername());
        busiSrtpRouteTable.setCreateTime(DateUtils.getNowDate());
        busiSrtpRouteTable.setUpdateBy(SecurityUtils.getUsername());
        busiSrtpRouteTable.setUpdateTime(DateUtils.getNowDate());
        busiSrtpRouteTableMapper.insertBusiSrtpRouteTable(busiSrtpRouteTable);
    }

    /**
     * 通过路由中的网元、端口在邻接标签表中对比找到对应的（源宿）邻接表
     * @param elementId
     * @param portId
     */
    private String findNeibLabelByParams(String elementId, String portId) {
        String neighbLabel = "";
        BusiNeighbLabel startNeighParam = new BusiNeighbLabel();
        startNeighParam.setStartElement(elementId);
        startNeighParam.setStartPortId(portId);
        List<BusiNeighbLabelListVo> startNeighs = busiNeighbLabelMapper.selectBusiNeighbLabelList(startNeighParam);

        BusiNeighbLabel endNeighParam = new BusiNeighbLabel();
        endNeighParam.setEndElement(elementId);
        endNeighParam.setEndPortId(portId);

        List<BusiNeighbLabelListVo> endNeighs = busiNeighbLabelMapper.selectBusiNeighbLabelList(endNeighParam);
        if (!CollectionUtils.isEmpty(startNeighs)){
            neighbLabel = startNeighs.get(0).getStartNeighbLabel();
        }
        if (!CollectionUtils.isEmpty(endNeighs)){
            neighbLabel = endNeighs.get(0).getEndNeighbLabel();
        }
        return neighbLabel;

    }

    /**
     * 插入路由图网元（顺序）对象
     *
     * @param SrtpId
     * @param shortestRoute
     * @param elementMap
     */
    private void insertBusiSrtpRouteElementsBatch(String SrtpId, List<String> shortestRoute, Map<String, String> elementMap, String routeType) {
        for (String elementId : shortestRoute) {
            BusiSrtpRouteElements busiSrtpRouteElements = new BusiSrtpRouteElements();
            busiSrtpRouteElements.setId(IdUtils.simpleUUID());
            busiSrtpRouteElements.setSrtpId(SrtpId);
            busiSrtpRouteElements.setElementId(elementId);
            busiSrtpRouteElements.setElementName(elementMap.get(elementId));
            busiSrtpRouteElements.setRouteType(routeType);
            busiSrtpRouteElements.setCreateBy(SecurityUtils.getUsername());
            busiSrtpRouteElements.setCreateTime(DateUtils.getNowDate());
            busiSrtpRouteElements.setUpdateBy(SecurityUtils.getUsername());
            busiSrtpRouteElements.setUpdateTime(DateUtils.getNowDate());
            busiSrtpRouteElementsMapper.insertBusiSrtpRouteElements(busiSrtpRouteElements);
        }
    }

    /**
     * 更新路由图表信息
     *
     * @param busiSrtpVo
     */
    void updateBusiSrtpRouteGraph(BusiSrtpVo busiSrtpVo) {
        busiSrtpRouteGraphMapper.deleteBusiSrtpRouteGraphBySrtpId(busiSrtpVo.getId());
        busiSrtpRouteElementsMapper.deleteBusiSrtpRouteElementsBySrtpId(busiSrtpVo.getId());
        busiSrtpRouteTableMapper.deleteBusiSrtpRouteTableBySrtpId(busiSrtpVo.getId());
        insertBusiSrtpRouteGraph(busiSrtpVo);
    }

    /**
     * 修改业务-srtp配置
     *
     * @param busiSrtp 业务-srtp配置
     * @return 结果
     */
    @Override
    public int updateBusiSrtp(BusiSrtp busiSrtp) {
        //状态设置为已完成
        busiSrtp.setUpdateBy(SecurityUtils.getUsername());
        busiSrtp.setUpdateTime(DateUtils.getNowDate());
        return busiSrtpMapper.updateBusiSrtp(busiSrtp);
    }

    /**
     * 批量删除业务-srtp配置
     *
     * @param ids 需要删除的业务-srtp配置主键
     * @return 结果
     */
    @Override
    public int deleteBusiSrtpByIds(String[] ids) {
        return busiSrtpMapper.deleteBusiSrtpByIds(ids);
    }

    /**
     * 删除业务-srtp配置信息
     *
     * @param id 业务-srtp配置主键
     * @return 结果
     */
    @Override
    public int deleteBusiSrtpById(String id) {
        return busiSrtpMapper.deleteBusiSrtpById(id);
    }

    @Override
    public List<BusiSrtpListVo> selectBusiSrtpEleList(BusiSrtpListVo busiSrtp) {
        return busiSrtpMapper.selectBusiSrtpEleList(busiSrtp);
    }

    /**
     * @param subLines
     * @return
     */
    public List<List<NetElementLinkVo>> combine(List<List<NetElementLinkVo>> subLines) {
        List<List<NetElementLinkVo>> result = new ArrayList<>();
        if (subLines == null || subLines.isEmpty()) {
            return result;
        }
        backtrack(subLines, 0, new ArrayList<>(), result);
        return result;
    }

    private void backtrack(List<List<NetElementLinkVo>> subLines, int index, List<NetElementLinkVo> currentCombination, List<List<NetElementLinkVo>> result) {
        if (index == subLines.size()) {
            result.add(new ArrayList<>(currentCombination));
            return;
        }
        List<NetElementLinkVo> currentList = subLines.get(index);
        for (NetElementLinkVo element : currentList) {
            currentCombination.add(element);
            backtrack(subLines, index + 1, currentCombination, result);
            currentCombination.remove(currentCombination.size() - 1);
        }
    }
}
